package com.vshop.platform.system.crud.dao;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.vshop.platform.system.domain.entity.SysRole;
import com.vshop.platform.system.domain.entity.SysRoleMenu;
import com.vshop.platform.system.crud.mapper.SysRoleMenuMapper;
import com.vshop.platform.system.domain.param.SysRoleParam;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.mybatisflex.core.query.QueryMethods.select;
import static com.vshop.platform.system.domain.entity.table.SysMenuTableDef.SysMenuTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleMenuTableDef.SysRoleMenuTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleTableDef.SysRoleTable;


/**
 * 角色和菜单关联表 服务层实现。
 *
 * @author vshop
 * @since 2024-11-18
 */
@RequiredArgsConstructor
@Slf4j
@Repository
public class SysRoleMenuDao extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> {

    /**
     * 根据角色ID查询菜单树信息(已分配)
     *
     * @param roleId 角色ID
     * @return 选中菜单列表
     */
    public List<Long> listAllocatedMenuIdByRoleId(Long roleId) {
        SysRole role = this.queryChain()
                .from(SysRoleTable)
                .where(SysRoleTable.RoleId.eq(roleId))
                .oneAs(SysRole.class);

        /*select m.menu_id
        from sys_menu m
        left join sys_role_menu rm on m.menu_id = rm.menu_id
        where rm.role_id = #{roleId}
            <if test="menuCheckStrictly">
            and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
            </if>
        order by m.parent_id, m.order_num*/
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysMenuTable.MenuId)
                .from(SysMenuTable)
                .leftJoin(SysRoleMenuTable).on(SysRoleMenuTable.MenuId.eq(SysMenuTable.MenuId))
                .where(SysRoleMenuTable.RoleId.eq(roleId));

        if (role.getMenuCheckStrictly()) {
            queryWrapper.and(SysMenuTable.MenuId.notIn(
                    select(SysMenuTable.ParentId).from(SysMenuTable)
                            .innerJoin(SysRoleMenuTable).on(
                                    SysMenuTable.MenuId.eq(SysRoleMenuTable.MenuId))
                            .and(SysRoleMenuTable.RoleId.eq(roleId))
            ));
        }
        queryWrapper.orderBy(SysMenuTable.ParentId.asc(), SysMenuTable.SortNum.asc());
        return this.listAs(queryWrapper, Long.class);
    }


    /**
     * 新增角色菜单信息 (菜单权限)
     *
     * @param param 角色对象
     * @return true 保存成功，false 保存失败
     */
    @Transactional
    public boolean saveRoleMenu(SysRoleParam param) {
        boolean inserted = true;
        // 新增用户与角色管理
        List<SysRoleMenu> list = new ArrayList<>();
        Optional.ofNullable(param.getMenuIds()).orElse(List.of())
                .forEach(menuId -> {
                    SysRoleMenu rm = new SysRoleMenu();
                    rm.setRoleId(param.getRoleId());
                    rm.setMenuId(menuId);
                    list.add(rm);
                });
        if (CollUtil.isNotEmpty(list)) {
            inserted = this.saveBatch(list);
        }
        return inserted;
    }

    /**
     * 通过角色ID删除用户和菜单关联
     *
     * @param roleId 角色ID
     * @return 结果:true 删除成功，false 删除失败
     */
    public boolean removeRoleMenuByRoleId(Long roleId) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(SysRoleMenuTable)
                .where(SysRoleMenuTable.RoleId.eq(roleId));
        return this.remove(queryWrapper);
    }

    /**
     * 批量删除角色菜单关联信息
     * delete from sys_role_menu where role_id in
     *
     * @param roleIds 需要删除的数据ID
     * @return true 删除成功，false 删除失败。
     */
    public boolean removeRoleMenuByRoleIds(List<Long> roleIds) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(SysRoleMenuTable)
                .where(SysRoleMenuTable.RoleId.in(roleIds));
        return this.remove(queryWrapper);
    }

    /**
     * 检验菜单是否存在角色
     * select count(1) from sys_role_menu where menu_id = #{menuId}
     *
     * @param menuId 菜单ID
     * @return 结果
     */
//    public boolean checkMenuHasRoleByMenuId(Long menuId) {
//        QueryWrapper queryWrapper = QueryWrapper.create()
//                .select(QueryMethods.count(SysRoleMenuTable.RoleId))
//                .from(SysRoleMenuTable)
//                .where(SysRoleMenuTable.MenuId.eq(menuId));
//        return this.count(queryWrapper) > 0;
//    }
}
